package org.moyrax.nereyda.lib
{
	import mx.formatters.DateBase;

	public class DateISO extends DateBase
	{
		public static const FORMAT_YEAR           :int = 1;
		public static const FORMAT_SMALL_DATE     :int = 2;
		public static const FORMAT_FULL_DATE      :int = 3;
		public static const FORMAT_SMALL_DATETIME :int = 4;
		public static const FORMAT_FULL_DATETIME  :int = 5;
		public static const FORMAT_LARGE_DATETIME :int = 6;
		
		private var sysDate : Date;
		
		public function DateISO( date:Object )
		{
			super();
			
			if ( date && (date is String) ) {
				this.parseISO( date as String );
			}
			else if ( date && (date is Date) ) {
				this.setDate( date as Date );
			}
		}
		
		/**
		 * Establece el valor del objeto convirtiendo
		 * una fecha ISO 8601 al formato Date.
		 */
		public function parseISO( isoDate:String ):void
		{
			isoDate = isoDate.replace(/-/g, "/");
			isoDate = isoDate.replace("T", " ");
			isoDate = isoDate.replace("Z", " GMT-0000");
			
			const iTime:Number = Date.parse(isoDate);

			if (iTime < 0)
				this.sysDate = null;
			else
				this.sysDate = new Date(iTime);
		}
		
		public function setDate( date:Date ):void
		{
			this.sysDate = date;
		}
		
		/**
		 * Devuelve el objeto Date vinculado a esta instancia.
		 */
		public function toDate():Date
		{
			return( this.sysDate );
		}
		
		/**
		 * Convierte la fecha al formato de fecha ISO 8601.
		 * 
		 * @param format Formato que se le dará a la fecha.
		 * @param offset Determina si se utilizará la parte de milisegundos.
		 * 
		 * @return Devuelve un String con la fecha formateada.
		 */
		public function toISO(format:int = FORMAT_FULL_DATETIME, offset:String = null):String
		{
			var date : Date = null;
			
			if (!format) {
				format = 6;
			}

		    if (!offset) {
		        offset = 'Z';
		        date = this.sysDate;
		    }
		    else {
		        var d : Array = offset.match(/([-+])([0-9]{2}):([0-9]{2})/);
		        var offsetnum : Number = (Number(d[2]) * 60) + Number(d[3]);
		        
		        offsetnum *= ((d[1] == '-') ? -1 : 1);
		        
		        date = new Date(Number(Number(this.sysDate) + (offsetnum * 60000)));
		    }
		
		    var zeropad : Function = function (num:int):String {
		    	return ((num < 10) ? '0' : '') + num; 
		    };
		    
		    var str     : String = "";
		    
		    str += date.getUTCFullYear();
		    
		    if (format > FORMAT_SMALL_DATE) {
		    	str += "-" + zeropad(date.getUTCMonth() + 1);
		    }
		    if (format > FORMAT_FULL_DATE) {
		    	str += "-" + zeropad(date.getUTCDate());
		    }
		    if (format > FORMAT_SMALL_DATETIME) {
		        str += "T" + zeropad(date.getUTCHours()) +
		               ":" + zeropad(date.getUTCMinutes());
		    }
		    
		    if (format > FORMAT_FULL_DATETIME) {
		        var secs:Number = Number(date.getUTCSeconds() + "." +
		                   ((date.getUTCMilliseconds() < 100) ? '0' : '') +
		                   zeropad(date.getUTCMilliseconds()));
		        str += ":" + zeropad(secs);
		    }
		    else if (format > FORMAT_LARGE_DATETIME) {
		    	str += ":" + zeropad(date.getUTCSeconds());
		    }
		
		    if (format > FORMAT_FULL_DATE) {
		    	str += offset;
		    }
		    
		    return( str );
		}
	}
}